#include <iostream>
#include <memory>
#include <unistd.h>
#include <mutex>
#include "Thread.hpp"

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int ticket = 1000;// 多人抢票

// 1.多个执行流进行安全访问的共享资源 -- 临界资源
// 2.我们把多个执行流中，访问临界资源的代码 -- 临界区 -- 往往是线程代码的很小的一部分
// 3.想让多个线程串行访问共享资源 -- 互斥
// 4.对一个资源进行访问的时候，要么不做，要么做完 -- 原子性，不是原子性的情况 -- 一个的资源进行的操作，如果只用一条汇编就能完成 -- 原子性
// 反之： 不是原子的 

// 提出解决方案：加锁！

// 就需要尽可能让多个线程交叉执行
// 多个线程交叉执行的本质：就是让调度器尽可能的频繁发送进程调度与切换
// 线程一般什么时候进行切换？ 时间片到了，来了更改优先级的线程，线程等待的时候。
// 线程是在什么时候检测上面的问题呢？从内核态返回用户态的时候，线程对调度状态进行检测，如果可以，就直接发生线程切换

void *getTicket(void *args)
{
    std::string username = static_cast<const char *>(args);
    while (true)
    {
        pthread_mutex_lock(&lock);
        if (ticket > 0)// 判断的本质逻辑： 1.读取内存数据cpu内的寄存器中 2.进行判断
        {
            usleep(100);//极端条件，tickrt==1，sleep(线程都能进来)，线程上下文都是1
            std::cout << username << "正在进行抢票: " << ticket << std::endl;
            ticket--;
            pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
    }
    return nullptr;
}
int main()
{
    // Thread(func_t func,void* args,int number);
    std::unique_ptr<Thread> thread1(new Thread(getTicket, (void *)"hello world", 1));
    std::unique_ptr<Thread> thread2(new Thread(getTicket, (void *)"count world", 2));
    std::unique_ptr<Thread> thread3(new Thread(getTicket, (void *)"log world", 3));
    thread1->start();
    thread2->start();
    thread3->start();

    thread1->join();
    thread2->join();
    thread3->join();
    return 0;
}
/////////////////////////////////////////////////////////////////////////////////

// 对变量进行++，或者--，在C、C++上，看起来只有一条语句，但是在汇编之后只是是三条语句：
// 1.从内存读取数据到CPU寄存器中
// 2.在寄存器中让CPU进行对应的算逻运算
// 3.写回新的结果到内存中变量的位置

// 我们定义全局变量，在没有保护的是，往往是不安全的，像上面多个线程在交替执行造成的数据安全问题，称为数据不一致问题！